﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace PP.PaintLib
{
    public class PPImage
    {
        /// <summary>
        /// 判断文件是否为图片
        /// </summary>
        /// <param name="path">文件的完整路径</param>
        /// <returns></returns>
        public static bool IsImage(string path)
        {
            try
            {
                Image image = Image.FromFile(path);
                image.Dispose();
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// 获取屏幕截图
        /// </summary>
        /// <returns>截取到的图片</returns>
        public static Image GetImageFromScreen()
        {
            return GetImageFromScreen(Point.Empty, Screen.GetBounds(Point.Empty).Size);
        }

        /// <summary>
        /// 获取屏幕截图
        /// </summary>
        /// <param name="UpperLeftSource">相对于左上角的坐标</param>
        /// <param name="Size">图片大小</param>
        /// <returns>截取到的图片</returns>
        public static Image GetImageFromScreen(Point upLeftSourse, Size size)
        {
            // 创建一个bitmap对象并将其设置为屏幕大小
            var bitmap = new Bitmap(size.Width, size.Height);
            // 创建一个Graphics对象并将其设置为
            using (Graphics g = Graphics.FromImage(bitmap))
            {
                // 将整个屏幕绘制到Graphics对象中
                g.CopyFromScreen(upLeftSourse, Point.Empty, size);
            }
            return bitmap;
        }

        /// <summary>
        /// 载入图片（不占用文件）
        /// </summary>
        /// <param name="imagePath"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public static Image LoadImage(string imagePath)
        {
            using (FileStream fileStream = new FileStream(imagePath, FileMode.Open, FileAccess.Read))
            {
                int byteLen = (int)fileStream.Length;
                byte[] fileBytes = new byte[byteLen];
                fileStream.Read(fileBytes, 0, byteLen);
                return Image.FromStream(new MemoryStream(fileBytes));
            }
        }

        /// <summary>
        /// 限定范围：【min,max】
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="value">传入数据</param>
        /// <param name="min">最小值</param>
        /// <param name="max">最大值</param>
        /// <returns></returns>
        public static T VerifyValue<T>(T data, T min, T max) where T : IComparable<T>
        {
            return data.CompareTo(min) < 0 ? min : data.CompareTo(max) > 0 ? max : data;
        }

        #region 图片效果

        #region 0、高斯模糊

        /// <summary>
        /// 模糊半径
        /// </summary>
        private static int BlurRadius { get; set; }
        private static Bitmap SourceImage { get; set; }
        private static List<double> BlurArray { get; set; }
        private static int MaxWidth { get; set; }
        private static int MaxHeight { get; set; }
        /// <summary>
        /// 获取高斯模糊效果后的图片
        /// </summary>
        /// <param name="image">原图</param>
        /// <param name="blurRadius">模糊半径</param>
        /// <returns></returns>
        public static Image GaussianBlurImage(Image image, int blurRadius)
        {
            if (image == null) return null;

            BlurArray = new List<double>();
            BlurRadius = blurRadius;
            SourceImage = new Bitmap(image);
            MaxWidth = SourceImage.Width - 1;
            MaxHeight = SourceImage.Height - 1;

            SetBlurArray(blurRadius);

            int width = image.Width, height = image.Height;
            Bitmap newImage = new Bitmap(width, height);


            LockBitmap lockBmp = new LockBitmap(new Bitmap(image));
            LockBitmap newLockBmp = new LockBitmap(newImage);
            lockBmp.LockBits();
            newLockBmp.LockBits();

            for (int y = 0; y < SourceImage.Height; y++)
            {
                for (int x = 0; x < SourceImage.Width; x++)
                {
                    var nC = GetBlurColor(x, y, lockBmp);
                    newLockBmp.SetPixel(x, y, nC);
                }
            }

            lockBmp.UnlockBits();
            newLockBmp.UnlockBits();

            return newImage;

        }

        /// <summary>
        /// 获取高斯模糊的颜色值
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        private static Color GetBlurColor(int x, int y, LockBitmap lockBitmap)
        {
            double r = 0, g = 0, b = 0;
            int index = 0;
            for (var t = y - BlurRadius; t <= y + BlurRadius; t++)
            {
                for (var l = x - BlurRadius; l <= x + BlurRadius; l++)
                {
                    var color = GetDefautColor(l, t, lockBitmap);
                    var weighValue = BlurArray[index];
                    r += color.R * weighValue;
                    g += color.G * weighValue;
                    b += color.B * weighValue;
                    index++;
                }
            }
            return Color.FromArgb((byte)r, (byte)g, (byte)b);
        }

        private static Color GetDefautColor(int x, int y, LockBitmap lockBitmap)
        {
            x = VerifyValue(x, 0, MaxWidth);
            y = VerifyValue(y, 0, MaxHeight);
            return lockBitmap.GetPixel(x, y);
        }

        /// <summary>
        /// 设置权重数组
        /// </summary>
        /// <param name="blurRadius"></param>
        private static void SetBlurArray(int blurRadius)
        {
            BlurArray = new List<double>();
            int blur = blurRadius;
            double sum = 0;
            for (var y = blur; y >= blur * -1; y--)
            {
                for (var x = blur * -1; x <= blur; x++)
                {
                    var d = GetWeighing(x, y, blurRadius);
                    BlurArray.Add(d);
                    sum += d;
                }
            }
            for (var i = 0; i < BlurArray.Count; i++)
            {
                BlurArray[i] = BlurArray[i] / sum;
            }
        }

        /// <summary>
        /// 获取权重
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="blurRadius"></param>
        /// <returns></returns>
        private static double GetWeighing(int x, int y,int blurRadius)
        {
            double q = (blurRadius * 2 + 1) / 2;
            return 1 / (2 * Math.PI * Math.Pow(q, 2)) * Math.Exp(-(x * x + y * y) / (2 * q * q));
        }

        #endregion

        #region 1、旋转（90度，180度，270度）

        /// <summary>
        /// 旋转（90度，180度，270度）
        /// </summary>
        /// <param name="image">原图</param>
        /// <param name="angle">旋转角度</param>
        /// <returns></returns>
        public static Image RotateImage(Image image, int angle)
        {
            if (image == null) return null;

            int width = image.Width, height = image.Height;
            Point[] points = new Point[3] { new Point(0, 0), new Point(0, 0), new Point(0, 0) };
            Bitmap newBmp = new Bitmap(width, height);
            {
                switch (angle)
                {
                    case 90:
                        newBmp = new Bitmap(height, width);
                        points = new Point[3]{
                            new Point(height, 0),// 上左
                            new Point(height, width),// 上右
                            new Point(0, 0)//下左
                        };
                        break;
                    case 180:
                        newBmp = new Bitmap(width, height);
                        points = new Point[3]{
                            new Point(width, height),// 上左
                            new Point(0, height),// 上右
                            new Point(width, 0)//下左
                        };
                        break;
                    case 270:
                        newBmp = new Bitmap(height, width);
                        points = new Point[3]{
                            new Point(0, width),// 上左
                            new Point(0, 0),// 上右
                            new Point(height, width)//下左
                        };
                        break;
                    default:
                        break;
                }

                using (Graphics g = Graphics.FromImage(newBmp))
                {
                    g.DrawImage(image, points);
                }

                return newBmp;
            }
        }

        #endregion

        #region 2、重设大小

        /// <summary>
        /// 重设大小
        /// </summary>
        /// <param name="image">原图</param>
        /// <param name="size">新的尺寸</param>
        /// <returns></returns>
        public static Image ResizeImage(Image image, Size size)
        {
            if (image == null) return null;

            size.Width = VerifyValue(size.Width, 0, size.Width); 
            size.Height = VerifyValue(size.Height, 0, size.Height); 
            Bitmap newBmp = new Bitmap(size.Width, size.Height);
            using (Graphics g = Graphics.FromImage(newBmp))
            {
                g.DrawImage(image, new Rectangle(Point.Empty, size));
            }
            return newBmp;
        }

        #endregion

        #region 3、底片效果（反色）（255-r, 255-g, 255-b）

        /// <summary>
        /// 底片效果（反色）（255-r, 255-g, 255-b）
        /// </summary>
        /// <param name="image">原图</param>
        /// <returns></returns>
        public static Image NegativeImage(Image image)
        {
            if (image == null) return null;

            Bitmap sourseBmp = new Bitmap(image);

            int width = image.Width, height = image.Height;
            Bitmap newBmp = new Bitmap(width, height);

            LockBitmap lockBmp = new LockBitmap(sourseBmp);
            LockBitmap newLockBmp = new LockBitmap(newBmp);
            lockBmp.LockBits();
            newLockBmp.LockBits();

            for (int x = 1; x < width; x++)
            {
                for (int y = 1; y < height; y++)
                {
                    Color pixel = lockBmp.GetPixel(x, y);
                    int r = 255 - pixel.R;
                    int g = 255 - pixel.G;
                    int b = 255 - pixel.B;
                    newLockBmp.SetPixel(x, y, Color.FromArgb(r, g, b));
                }
            }

            lockBmp.UnlockBits();
            newLockBmp.UnlockBits();

            sourseBmp?.Dispose();

            return newBmp;
        }

        #endregion

        #region 4、黑白效果

        /// <summary>
        /// 黑白效果
        /// </summary>
        /// <param name="image">原图</param>
        /// <param name="type">0:平均值法；1:最大值法；2:加权平均值法</param>
        /// <returns></returns>
        public static Image GrayImage(Image image, int type)
        {
            if (image == null) return null;

            Bitmap sourseBmp = new Bitmap(image);

            int width = image.Width, height = image.Height;
            Bitmap newBmp = new Bitmap(width, height);

            LockBitmap lockBmp = new LockBitmap(sourseBmp);
            LockBitmap newLockBmp = new LockBitmap(newBmp);
            lockBmp.LockBits();
            newLockBmp.LockBits();

            for (int x = 0; x < width; x++)
            {
                for (int y = 0; y < height; y++)
                {
                    Color pixel = lockBmp.GetPixel(x, y);
                    int r = pixel.R;
                    int g = pixel.G;
                    int b = pixel.B;
                    int result = 0;
                    switch (type)
                    {
                        case 0://平均值法
                            result = (r + g + b) / 3;
                            break;
                        case 1://最大值法
                            result = Math.Max(r, Math.Max(g, b));
                            break;
                        case 2://加权平均值法
                            result = (int)(0.3 * r) + (int)(0.59 * g) + (int)(0.11 * b);
                            break;
                        default:
                            break;
                    }
                    newLockBmp.SetPixel(x, y, Color.FromArgb(result, result, result));
                }
            }

            lockBmp.UnlockBits();
            newLockBmp.UnlockBits();

            sourseBmp?.Dispose();

            return newBmp;
        }

        #endregion

        #region 5、浮雕：找出附近的像素点rgb，abs（rgb1-rgb2+128）

        /// <summary>
        /// 浮雕效果
        /// </summary>
        /// <param name="image">原图</param>
        /// <returns></returns>
        public static Image EmbossmentImage(Image image)
        {
            if (image == null) return null;

            int width = image.Width, height = image.Height;
            Bitmap newBmp = new Bitmap(width, height);

            LockBitmap lockBmp = new LockBitmap(new Bitmap(image));
            LockBitmap newLockBmp = new LockBitmap(newBmp);
            lockBmp.LockBits();
            newLockBmp.LockBits();

            for (int x = 0; x < width - 1; x++)
            {
                for (int y = 0; y < height - 1; y++)
                {
                    Color pixel1 = lockBmp.GetPixel(x, y);
                    Color pixel2 = lockBmp.GetPixel(x + 1, y + 1);
                    int r = Math.Abs(pixel1.R - pixel2.R + 128);
                    int g = Math.Abs(pixel1.G - pixel2.G + 128);
                    int b = Math.Abs(pixel1.B - pixel2.B + 128);
                    //处理颜色值溢出
                    r = VerifyValue(r, 0, 255);
                    g = VerifyValue(g, 0, 255);
                    b = VerifyValue(b, 0, 255);

                    newLockBmp.SetPixel(x, y, Color.FromArgb(r, g, b));
                }
            }

            lockBmp.UnlockBits();
            newLockBmp.UnlockBits();

            return newBmp;

        }

        #endregion

        #region 6、柔化

        /// <summary>
        /// 柔化效果
        /// </summary>
        /// <param name="image">原图</param>
        /// <returns></returns>
        public static Image SoftenImage(Image image)
        {
            if (image == null) return null;

            Bitmap sourseBmp = new Bitmap(image);

            int width = image.Width, height = image.Height;
            Bitmap newBmp = new Bitmap(width, height);

            LockBitmap lockBmp = new LockBitmap(sourseBmp);
            LockBitmap newLockBmp = new LockBitmap(newBmp);
            lockBmp.LockBits();
            newLockBmp.LockBits();

            //高斯模板 9
            int[] Gauss = { 1, 2, 1, 2, 4, 2, 1, 2, 1 };
            for (int x = 1; x < width - 1; x++)
            {
                for (int y = 1; y < height - 1; y++)
                {
                    int r = 0, g = 0, b = 0;
                    int index = 0;
                    for (int col = -1; col <= 1; col++)
                    {
                        for (int row = -1; row <= 1; row++, index++)
                        {
                            Color pixel = lockBmp.GetPixel(x + row, y + col);
                            r += pixel.R * Gauss[index];
                            g += pixel.G * Gauss[index];
                            b += pixel.B * Gauss[index];
                        }
                    }

                    r /= 16; g /= 16; b /= 16;
                    //处理颜色值溢出
                    r = VerifyValue(r, 0, 255);
                    g = VerifyValue(g, 0, 255);
                    b = VerifyValue(b, 0, 255);

                    newLockBmp.SetPixel(x - 1, y - 1, Color.FromArgb(r, g, b));
                }
            }

            lockBmp.UnlockBits();
            newLockBmp.UnlockBits();

            sourseBmp?.Dispose();

            return newBmp;

        }

        #endregion

        #region 7、锐化

        /// <summary>
        /// 锐化效果
        /// </summary>
        /// <param name="image">原图</param>
        /// <returns></returns>
        public static Image SharpenImage(Image image)
        {
            if (image == null) return null;

            Bitmap sourseBmp = new Bitmap(image);

            int width = image.Width, height = image.Height;
            Bitmap newBmp = new Bitmap(width, height);

            LockBitmap lockBmp = new LockBitmap(sourseBmp);
            LockBitmap newLockBmp = new LockBitmap(newBmp);
            lockBmp.LockBits();
            newLockBmp.LockBits();

            //拉普拉斯模板 9
            int[] Laplacian = { -1, -1, -1, -1, 9, -1, -1, -1, -1 };
            for (int x = 1; x < width - 1; x++)
            {
                for (int y = 1; y < height - 1; y++)
                {
                    int r = 0, g = 0, b = 0;
                    int index = 0;
                    for (int col = -1; col <= 1; col++)
                    {
                        for (int row = -1; row <= 1; row++, index++)
                        {
                            Color pixel = lockBmp.GetPixel(x + row, y + col);
                            r += pixel.R * Laplacian[index];
                            g += pixel.G * Laplacian[index];
                            b += pixel.B * Laplacian[index];
                        }
                    }

                    //处理颜色值溢出
                    r = VerifyValue(r, 0, 255);
                    g = VerifyValue(g, 0, 255);
                    b = VerifyValue(b, 0, 255);

                    newLockBmp.SetPixel(x - 1, y - 1, Color.FromArgb(r, g, b));
                }
            }

            lockBmp.UnlockBits();
            newLockBmp.UnlockBits();


            sourseBmp?.Dispose();

            return newBmp;

        }

        #endregion

        #region 8、雾化

        /// <summary>
        /// 雾化效果
        /// </summary>
        /// <param name="image">原图</param>
        /// <returns></returns>
        public static Image AtomizationImage(Image image)
        {
            if (image == null) return null;

            Bitmap sourseBmp = new Bitmap(image);

            int width = image.Width, height = image.Height;
            Bitmap newBmp = new Bitmap(width, height);

            LockBitmap lockBmp = new LockBitmap(sourseBmp);
            LockBitmap newLockBmp = new LockBitmap(newBmp);
            lockBmp.LockBits();
            newLockBmp.LockBits();

            Random rnd = new Random();
            for (int x = 1; x < width - 1; x++)
            {
                for (int y = 1; y < height - 1; y++)
                {
                    int k = rnd.Next(123456);
                    //像素块大小
                    int dx = x + k % 19;
                    int dy = y + k % 19;
                    dx = dx >= width ? width - 1 : dx;
                    dy = dy >= height ? height - 1 : dy;
                    Color pixel = lockBmp.GetPixel(dx, dy);

                    newLockBmp.SetPixel(x, y, pixel);
                }
            }

            lockBmp.UnlockBits();
            newLockBmp.UnlockBits();

            sourseBmp?.Dispose();

            return newBmp;
        }

        #endregion

        #region 9、马赛克

        /// <summary>
        /// 马赛克效果
        /// </summary>
        /// <param name="image">原图</param>
        /// <param name="mosaicValue">马赛克阙值</param>
        /// <returns></returns>
        public static Image MosaicImage(Image image,int mosaicValue)
        {
            if (image == null) return null;

            Bitmap sourseBmp = new Bitmap(image);

            int width = image.Width, height = image.Height;
            Bitmap newBmp = new Bitmap(width, height);

            LockBitmap lockBmp = new LockBitmap(sourseBmp);
            LockBitmap newLockBmp = new LockBitmap(newBmp);
            lockBmp.LockBits();
            newLockBmp.LockBits();


            for (int h = 0; h < height; h+=mosaicValue)
            {
                for (int w = 0; w < width; w+=mosaicValue)
                {
                    int r = 0, g = 0, b = 0, count = 0;//获取像素点（r,g,b）平均值
                    for (int x = w; x < w + mosaicValue && x < width; x++)
                    {
                        for (int y = h; y < h + mosaicValue && y < height; y++)
                        {
                            Color pixel = lockBmp.GetPixel(x, y);
                            r += pixel.R;
                            g += pixel.G;
                            b += pixel.B;
                            count++;
                        }
                    }

                    r /= count;
                    g /= count;
                    b /= count;


                    //填充(r,g,b)平均值
                    for (int x = w; x < w + mosaicValue && x < width; x++)
                    {
                        for (int y = h; y < h + mosaicValue && y < height; y++)
                        {
                            Color pixel = Color.FromArgb(r, g, b);
                            newLockBmp.SetPixel(x, y, pixel);
                        }
                    }
                }
            }

            lockBmp.UnlockBits();
            newLockBmp.UnlockBits();

            sourseBmp?.Dispose();

            return newBmp;
        }

        #endregion

        #region 10、滤色

        /// <summary>
        /// 滤色效果
        /// </summary>
        /// <param name="image">原图</param>
        /// <returns></returns>
        public static Image FilterColourImage(Image image)
        {
            if (image == null) return null;

            Bitmap sourseBmp = new Bitmap(image);

            int width = image.Width, height = image.Height;
            Bitmap newBmp = new Bitmap(width, height);

            LockBitmap lockBmp = new LockBitmap(sourseBmp);
            LockBitmap newLockBmp = new LockBitmap(newBmp);
            lockBmp.LockBits();
            newLockBmp.LockBits();


            for (int x = 0; x < width; x ++)
            {
                for (int y = 0; y < height; y ++)
                {
                    Color pixel=lockBmp.GetPixel(x, y);
                    newLockBmp.SetPixel(x, y, Color.FromArgb(0, pixel.G, pixel.B));
                }
            }

            lockBmp.UnlockBits();
            newLockBmp.UnlockBits();

            sourseBmp?.Dispose();

            return newBmp;
        }

        #endregion

        #region 11、亮度

        /// <summary>
        /// 亮度处理效果
        /// </summary>
        /// <param name="image">原图</param>        
        /// <param name="lightValue">增加或减少亮度(-255至255)</param>
        /// <returns></returns>
        public static Image FilterLightImage(Image image,int lightValue)
        {
            if (image == null) return null;

            Bitmap sourseBmp = new Bitmap(image);

            int width = image.Width, height = image.Height;
            Bitmap newBmp = new Bitmap(width, height);

            LockBitmap lockBmp = new LockBitmap(sourseBmp);
            LockBitmap newLockBmp = new LockBitmap(newBmp);
            lockBmp.LockBits();
            newLockBmp.LockBits();


            for (int x = 0; x < width; x++)
            {
                for (int y = 0; y < height; y++)
                {
                    Color pixel = lockBmp.GetPixel(x, y);
                    int r = VerifyValue(pixel.R + lightValue, 0, 255);
                    int g = VerifyValue(pixel.G + lightValue, 0, 255);
                    int b = VerifyValue(pixel.B + lightValue, 0, 255);
                    newLockBmp.SetPixel(x, y, Color.FromArgb(r, g, b));
                }
            }

            lockBmp.UnlockBits();
            newLockBmp.UnlockBits();

            sourseBmp?.Dispose();

            return newBmp;
        }

        #endregion

        #region 12、透明度

        /// <summary>
        /// 透明度处理效果
        /// </summary>
        /// <param name="image">原图</param>
        /// <param name="transparencyValue">透明度值(0-255)</param>
        /// <returns></returns>
        public static Image FilterTransparentImage(Image image, int transparencyValue)
        {
            if (image == null) return null;

            Bitmap sourseBmp = new Bitmap(image);

            int width = image.Width, height = image.Height;
            Bitmap newBmp = new Bitmap(width, height);

            LockBitmap lockBmp = new LockBitmap(sourseBmp);
            LockBitmap newLockBmp = new LockBitmap(newBmp);
            lockBmp.LockBits();
            newLockBmp.LockBits();


            for (int x = 0; x < height; x++)
            {
                for (int y = 0; y < width; y++)
                {
                    Color pixel = lockBmp.GetPixel(x, y);
                    newLockBmp.SetPixel(x, y, Color.FromArgb(transparencyValue, pixel.R, pixel.G, pixel.B));
                }
            }

            lockBmp.UnlockBits();
            newLockBmp.UnlockBits();

            sourseBmp?.Dispose();

            return newBmp;
        }

        #endregion

        #region 13、背景透明

        /// <summary>
        /// 背景颜色转透明处理效果
        /// </summary>
        /// <param name="image">原图</param>
        /// <param name="backColor">背景颜色</param>
        /// <returns></returns>
        public static Image MakeBackTransparentImage(Image image,Color backColor)
        {
            if (image == null) return null;

            Bitmap newBmp = new Bitmap(image);
            newBmp.MakeTransparent(backColor);
            return newBmp;
        }

        #endregion

        #endregion
    }

    #region 加快Bitmap的访问速度

    #region 1、内存法

    /// <summary>
    /// 这里定义一个类LockBitmap，通过把Bitmap数据拷贝出来，在内存上直接操作，操作完成后在拷贝到Bitmap中
    /// </summary>
    class LockBitmap
    {
        Bitmap source = null;
        IntPtr Iptr = IntPtr.Zero;
        BitmapData bitmapData = null;

        public byte[] Pixels { get; set; }
        public int Depth { get; private set; }
        public int Width { get; private set; }
        public int Height { get; private set; }

        public LockBitmap(Bitmap source)
        {
            this.source = source;
        }

        /// <summary>
        /// Lock bitmap data
        /// </summary>
        public void LockBits()
        {
            try
            {
                // Get width and height of bitmap
                Width = source.Width;
                Height = source.Height;

                // get total locked pixels count
                int PixelCount = Width * Height;

                // Create rectangle to lock
                Rectangle rect = new Rectangle(0, 0, Width, Height);

                // get source bitmap pixel format size
                Depth = System.Drawing.Bitmap.GetPixelFormatSize(source.PixelFormat);

                // Check if bpp (Bits Per Pixel) is 8, 24, or 32
                if (Depth != 8 && Depth != 24 && Depth != 32)
                {
                    throw new ArgumentException("Only 8, 24 and 32 bpp images are supported.");
                }

                // Lock bitmap and return bitmap data
                bitmapData = source.LockBits(rect, ImageLockMode.ReadWrite,
                                             source.PixelFormat);

                // create byte array to copy pixel values
                int step = Depth / 8;
                Pixels = new byte[PixelCount * step];
                Iptr = bitmapData.Scan0;

                // Copy data from pointer to array
                Marshal.Copy(Iptr, Pixels, 0, Pixels.Length);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Unlock bitmap data
        /// </summary>
        public void UnlockBits()
        {
            try
            {
                // Copy data from byte array to pointer
                Marshal.Copy(Pixels, 0, Iptr, Pixels.Length);

                // Unlock bitmap data
                source.UnlockBits(bitmapData);

                GC.Collect();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Get the color of the specified pixel
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public Color GetPixel(int x, int y)
        {
            Color clr = Color.Empty;

            // Get color components count
            int cCount = Depth / 8;

            // Get start index of the specified pixel
            int i = ((y * Width) + x) * cCount;

            if (i > Pixels.Length - cCount)
                throw new IndexOutOfRangeException();

            if (Depth == 32) // For 32 bpp get Red, Green, Blue and Alpha
            {
                byte b = Pixels[i];
                byte g = Pixels[i + 1];
                byte r = Pixels[i + 2];
                byte a = Pixels[i + 3]; // a
                clr = Color.FromArgb(a, r, g, b);
            }
            if (Depth == 24) // For 24 bpp get Red, Green and Blue
            {
                byte b = Pixels[i];
                byte g = Pixels[i + 1];
                byte r = Pixels[i + 2];
                clr = Color.FromArgb(r, g, b);
            }
            if (Depth == 8)
            // For 8 bpp get color value (Red, Green and Blue values are the same)
            {
                byte c = Pixels[i];
                clr = Color.FromArgb(c, c, c);
            }
            return clr;
        }

        /// <summary>
        /// Set the color of the specified pixel
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="color"></param>
        public void SetPixel(int x, int y, Color color)
        {
            // Get color components count
            int cCount = Depth / 8;

            // Get start index of the specified pixel
            int i = ((y * Width) + x) * cCount;

            if (Depth == 32) // For 32 bpp set Red, Green, Blue and Alpha
            {
                Pixels[i] = color.B;
                Pixels[i + 1] = color.G;
                Pixels[i + 2] = color.R;
                Pixels[i + 3] = color.A;
            }
            if (Depth == 24) // For 24 bpp set Red, Green and Blue
            {
                Pixels[i] = color.B;
                Pixels[i + 1] = color.G;
                Pixels[i + 2] = color.R;
            }
            if (Depth == 8)
            // For 8 bpp set color value (Red, Green and Blue values are the same)
            {
                Pixels[i] = color.B;
            }
        }
    }

    #endregion

    #region 2、指针法
    /// <summary>
    /// 这种方法访问速度比内存法更快，直接通过指针对内存进行操作，不需要进行拷贝，
    /// 但是在C#中直接通过指针操作内存是不安全的，所以需要在代码中加入unsafe关键字，在生成选项中把允许不安全代码勾上，才能编译通过
    /// </summary>
    public class PointBitmap
    {
        Bitmap source = null;
        IntPtr Iptr = IntPtr.Zero;
        BitmapData bitmapData = null;

        public int Depth { get; private set; }
        public int Width { get; private set; }
        public int Height { get; private set; }

        public PointBitmap(Bitmap source)
        {
            this.source = source;
        }

        public void LockBits()
        {
            try
            {
                // Get width and height of bitmap
                Width = source.Width;
                Height = source.Height;

                // get total locked pixels count
                int PixelCount = Width * Height;

                // Create rectangle to lock
                Rectangle rect = new Rectangle(0, 0, Width, Height);

                // get source bitmap pixel format size
                Depth = System.Drawing.Bitmap.GetPixelFormatSize(source.PixelFormat);

                // Check if bpp (Bits Per Pixel) is 8, 24, or 32
                if (Depth != 8 && Depth != 24 && Depth != 32)
                {
                    throw new ArgumentException("Only 8, 24 and 32 bpp images are supported.");
                }

                // Lock bitmap and return bitmap data
                bitmapData = source.LockBits(rect, ImageLockMode.ReadWrite,
                                             source.PixelFormat);

                //得到首地址
                unsafe
                {
                    Iptr = bitmapData.Scan0;
                    //二维图像循环

                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void UnlockBits()
        {
            try
            {
                source.UnlockBits(bitmapData);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public Color GetPixel(int x, int y)
        {
            unsafe
            {
                byte* ptr = (byte*)Iptr;
                ptr = ptr + bitmapData.Stride * y;
                ptr += Depth * x / 8;
                Color c = Color.Empty;
                if (Depth == 32)
                {
                    int a = ptr[3];
                    int r = ptr[2];
                    int g = ptr[1];
                    int b = ptr[0];
                    c = Color.FromArgb(a, r, g, b);
                }
                else if (Depth == 24)
                {
                    int r = ptr[2];
                    int g = ptr[1];
                    int b = ptr[0];
                    c = Color.FromArgb(r, g, b);
                }
                else if (Depth == 8)
                {
                    int r = ptr[0];
                    c = Color.FromArgb(r, r, r);
                }
                return c;
            }
        }

        public void SetPixel(int x, int y, Color c)
        {
            unsafe
            {
                byte* ptr = (byte*)Iptr;
                ptr = ptr + bitmapData.Stride * y;
                ptr += Depth * x / 8;
                if (Depth == 32)
                {
                    ptr[3] = c.A;
                    ptr[2] = c.R;
                    ptr[1] = c.G;
                    ptr[0] = c.B;
                }
                else if (Depth == 24)
                {
                    ptr[2] = c.R;
                    ptr[1] = c.G;
                    ptr[0] = c.B;
                }
                else if (Depth == 8)
                {
                    ptr[2] = c.R;
                    ptr[1] = c.G;
                    ptr[0] = c.B;
                }
            }
        }
    }

    #endregion

    #endregion

}
